﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Schema;
using System.Xml;
using System.Xml.XPath;
using System.IO;
using TathamOddie.OpenSearchValidator.Logic.Tasks;

namespace TathamOddie.OpenSearchValidator.Logic
{
	public class Validator
	{
		private readonly IWebLoader webLoader;

		public Validator()
			: this(new WebLoader())
		{
		}

		public Validator(IWebLoader webLoader)
		{
			this.webLoader = webLoader;
		}

		public Message[] Validate(Uri pageAddress, string searchTerms)
		{			
			var services = new ValidationServices()
			{
				WebLoader = webLoader
			};
			var state = new ValidationState()
			{
				PageUri = pageAddress,
				SearchTerms = searchTerms
			};
			var initialTasks = new IValidationTask[]
			{
				new RetrieveSourcePageTask()
			};
            
			var messages = new List<Message>();
			RunSteps(services, state, messages, initialTasks);

			return messages.ToArray();
		}

		static void RunSteps(ValidationServices services, ValidationState state, IList<Message> messages, IEnumerable<IValidationTask> tasks)
		{
			foreach (var task in tasks)
			{
				try
				{
					var result = task.Validate(services, state);
					foreach (var message in result.Messages)
					{
						messages.Add(message);
					}
				    if (!result.Messages.Any(m => m.Type == MessageType.Failure) &&
					    result.ChildTasks.Any())
					{
						RunSteps(services, state, messages, result.ChildTasks);
					}
				}
				catch (Exception ex)
				{
					messages.Add(new Message(MessageType.Failure, "An unexpected failure occurred. [{0}]", ex.GetType().Name));
				}
			}
		}
	}
}